package zredislock

import (
	"context"
	"fmt"
	"github.com/bsm/redislock"
	"github.com/redis/go-redis/v9"
	"time"
)

var (
	client *redis.Client
	locker *redislock.Client
)

type Lock struct {
	Lock *redislock.Lock
	Ctx  context.Context
	Err  error
}

func Init(addr, pass string, db int) {
	client = redis.NewClient(&redis.Options{
		Network:  "tcp",
		Addr:     addr,
		Password: pass,
		DB:       db,
	})

	locker = redislock.New(client)
}

// Obtain 获得锁
func Obtain(key string, ttl time.Duration, opt *redislock.Options) (lock *Lock) {
	lock = &Lock{
		Ctx: context.Background(),
	}
	l, err := locker.Obtain(lock.Ctx, key, ttl, opt)
	if err == redislock.ErrNotObtained {
		fmt.Println("Could not obtain lock!")
	} else if err != nil {
		fmt.Println(err)
	}
	lock.Lock = l
	lock.Err = err

	return
}

// Release 释放锁
func (l *Lock) Release() {
	err := l.Lock.Release(l.Ctx)
	if err != nil {
		fmt.Println(err)
	}
}

func GetOptionLimitRetry(duration time.Duration, max int) *redislock.Options {
	backoff := redislock.LimitRetry(redislock.LinearBackoff(duration), max)
	return &redislock.Options{
		RetryStrategy: backoff,
	}
}
